package common.tool.box.utils.charset;

import io.jsonwebtoken.lang.Collections;

import java.io.*;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.List;

public class CharsetUtils {
    private static final String PRE_FIX_UTF = "&#x";
    private static final String POS_FIX_UTF = ";";

    /**
     * 将字符串编码格式转成unicode
     */
    public static String XmlFormalize(String sTemp) {
        StringBuffer sb = new StringBuffer();

        if (sTemp == null || sTemp.equals("")) {
            return "";
        }
        String s = CharsetUtils.TranEncodeToGB2312(sTemp);
        for (int i = 0; i < s.length(); i++) {
            char cChar = s.charAt(i);
            if (CharsetUtils.isGB2312(cChar)) {
                sb.append(PRE_FIX_UTF);
                sb.append(Integer.toHexString(cChar));
                sb.append(POS_FIX_UTF);
            } else {
                switch ((int) cChar) {
                    case 32:
                        sb.append("&#32;");
                        break;
                    case 34:
                        sb.append("&quot;");
                        break;
                    case 38:
                        sb.append("&amp;");
                        break;
                    case 60:
                        sb.append("&lt;");
                        break;
                    case 62:
                        sb.append("&gt;");
                        break;
                    default:
                        sb.append(cChar);
                }
            }
        }
        return sb.toString();
    }

    /**
     * 将字符串编码格式转成GB2312
     */
    public static String TranEncodeToGB2312(String str) {
        try {
            String strEncode = CharsetUtils.getEncoding(str);
            String temp = new String(str.getBytes(strEncode), "GB2312");
            return temp;
        } catch (java.io.IOException ex) {
            return null;
        }
    }

    /**
     * 判断输入字符是否为gb2312的编码格式
     */
    public static boolean isGB2312(char c) {
        String sCh = Character.toString(c);
        try {
            byte[] bb = sCh.getBytes("gb2312");
            if (bb.length > 1) {
                return true;
            }
        } catch (java.io.UnsupportedEncodingException ex) {
            return false;
        }
        return false;
    }

    /**
     * 判断字符串的编码
     */
    public static String getEncoding(String str) {
        List<String> encode = Collections.arrayToList(new String[]{"GB2312", "ISO-8859-1", "UTF-8", "GBK"});
        for (String s : encode) {
            try {
                if (str.equals(new String(str.getBytes(s), s))) {
                    return s;
                }
            } catch (Exception e) {
                System.out.println("编码错误");
            }
        }
        return "";
    }

    /**
     * 文件字符集转换
     */
    public static String fileCharsetConvert(String filePath, String oldCharset, String newCharset) {
        File file = new File(filePath);
        if (!file.exists()) {
            return null;
        }
        try {
            InputStreamReader read = new InputStreamReader(Files.newInputStream(file.toPath()), oldCharset);
            BufferedReader bufferedReader = new BufferedReader(read);
            String lineTxt;
            StringBuilder sb = new StringBuilder();
            while ((lineTxt = bufferedReader.readLine()) != null) {
                sb.append(lineTxt).append("\r");
            }
            read.close();
            String content = sb.toString();
            FileOutputStream fos = new FileOutputStream(file);
            OutputStreamWriter osw = new OutputStreamWriter(fos, newCharset);
            osw.write(content);
            osw.flush();
            osw.close();
            return content;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 判断文件编码
     */
    public static String getFileEncode(String filePath) {
        String code;
        try {
            InputStream inputStream = Files.newInputStream(Paths.get(filePath));
            byte[] head = new byte[3];
            inputStream.read(head);
            code = "GBK";
            if (head[0] == -1 && head[1] == -2 )
                code = "UTF-16";
            if (head[0] == -2 && head[1] == -1 )
                code = "Unicode";
            if(head[0]==-17 && head[1]==-69 && head[2] ==-65)
                code = "UTF-8";
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        return code;
    }
}
